package com.bruce.tool.netty.socket.core;

import com.bruce.tool.common.util.LogUtils;
import com.bruce.tool.common.util.string.JsonUtils;
import com.bruce.tool.common.util.string.MapHandler;
import com.bruce.tool.common.util.string.StringUtils;
import com.bruce.tool.netty.socket.constant.ClientTypeEnum;
import com.bruce.tool.netty.socket.util.SocketUtils;
import com.google.common.collect.Maps;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Objects;

/**
 * @author bruce
 */
@Slf4j
@Sharable
public class SocketServerHandler extends ChannelInboundHandlerAdapter {

    private SocketServer server;

    public SocketServerHandler(SocketServer server) {
        this.server = server;
    }

    private Map<String,Channel> clients = Maps.newConcurrentMap();
    private Map<String,Channel> servers = Maps.newConcurrentMap();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if( !( msg instanceof ByteBuf ) ){ return; }
        String originMessage = SocketUtils.transfer((ByteBuf) msg);
        if (StringUtils.isEmpty(originMessage)){
            return;
        }
        Message clientMessage = JsonUtils.strToObj(originMessage,Message.class);
        String message = clientMessage.getBody();
        if(StringUtils.isEmpty(message)){
            return;
        }
        Channel incoming = ctx.channel();
        String clientId = clientMessage.getFrom().getClientId();
        // 发送心跳检测
        if( message.contains(server.getConfig().getPing()) ){
            LogUtils.info(log,"心跳检测,From:{},{}",JsonUtils.objToStr(clientMessage.getFrom()),message);
            if(ClientTypeEnum.SERVICE.getCode().equals(clientMessage.getFrom().getClientType())){
                servers.put(clientId,incoming);
            }else{
                clients.put(clientId,incoming);
            }
            Map body = MapHandler.build()
                    .add(server.getConfig().getPong(),System.currentTimeMillis());
            message = JsonUtils.objToStr(body);
            Message serverMessage = Message.builder()
                    .from(clientMessage.getTo())
                    .to(clientMessage.getFrom())
                    .body(message)
                    .build();
            String packInfo = JsonUtils.objToStr(serverMessage);
            msg = Unpooled.copiedBuffer(packInfo.getBytes());
            incoming.writeAndFlush(msg);
            return;
        }
        if(ClientTypeEnum.SERVICE.getCode().equals(clientMessage.getFrom().getClientType())){
            // 消息来源于客户端中的服务者,消息需要发送给所有客户
            for (Channel channel : clients.values()){
                if(Objects.nonNull(channel) ){
                    channel.writeAndFlush(msg);
                }
            }
        }else{
            //消息来源于客户端中的客户,消息需要发送给服务者
            int size = servers.size();
            if(size == 0){return;}
            for (Channel channel : servers.values()){
                if(Objects.nonNull(channel) ){
                    channel.writeAndFlush(msg);
                }
            }
        }
    }

}